package com.iwhalecloud.bss.kite.cucc.service.util;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class LocalSignature {

    /**
     * 签名
     *
     * @param params 参数
     * @param api_key 应用密钥
     * @param charset 字符编码
     * @return
     * @throws Exception
     */
    public static String sign(Map params, String api_key, String charset) throws Exception {
        String content = getSignContent(params, api_key);
        String sign = sign(content, charset);
        return sign;
    }

    /**
     * 验签
     *
     * @param params 参数
     * @param api_key 应用密钥
     * @return
     * @throws Exception
     */
    public static boolean signCheck(Map<String, String> params, String api_key, String charset) throws Exception {
        String content = getSignContent(params, api_key);
        String sign = sign(content, charset);
        String src_sign = "";
        Iterator it = params.keySet().iterator();
        while (it.hasNext()) {
            String k = (String) it.next();
            if ("sign".equalsIgnoreCase(k)) {
                src_sign = params.get(k);
                break;
            }
        }
        return sign.equals(src_sign);
    }

    public static String randomStr() {
        String template = "abcdefghijklmnopqrstuvwxyz0123456789";
        StringBuffer buffer = new StringBuffer();
        Random random = new Random();
        while (buffer.length() < 32) {
            int index = random.nextInt(36);
            char c = template.charAt(index);
            buffer.append(c);
        }
        return buffer.toString();
    }

    public static String getSignContent(Map<String, String> params, String api_key) {
        StringBuffer content = new StringBuffer();
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        String pre = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (!"sign".equalsIgnoreCase(key)) {
                if (key != null && value != null && !"".equals(value)) {
                    content.append(pre).append(key).append("=").append(value);
                    pre = "&";
                }
            }
        }
        return content.toString().concat("&key=").concat(api_key);
    }

    public static String sign(String src, String charset) throws Exception {
        if (charset == null || "".equals(charset)) {
            charset = "utf-8";
        }
        return byteArrayToHexString(md5Digest(src.getBytes(charset)));
    }

    public static byte[] md5Digest(byte[] src) throws Exception {
        MessageDigest alg = MessageDigest.getInstance("MD5");
        return alg.digest(src);
    }

    public static String byteArrayToHexString(byte[] b) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    public static String byteToString(byte[] bByte) {
        StringBuffer sBuffer = new StringBuffer();
        for (int i = 0; i < bByte.length; i++) {
            sBuffer.append(byteToArrayString(bByte[i]));
        }
        return sBuffer.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0) {
            n += 256;
        }
        int d1 = n / 16;
        int d2 = n % 16;
        return (new StringBuilder(String.valueOf(HEX_DIGITS[d1]))).append(HEX_DIGITS[d2]).toString();
    }

    private static String byteToArrayString(byte bByte) {
        int iRet = bByte;
        if (iRet < 0) {
            iRet += 256;
        }
        int iD1 = iRet / 16;
        int iD2 = iRet % 16;
        return (new StringBuilder(String.valueOf(STRING_DIGITS[iD1]))).append(STRING_DIGITS[iD2]).toString();
    }

    private static final String[] HEX_DIGITS = {
        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
    };

    private static final String[] STRING_DIGITS  = {
        "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"
    };

}
